#ifndef _BENCHAMX_UTILS_H__
#define _BENCHAMX_UTILS_H__

#include "stdio.h"
#include "stdlib.h"
#include "stdint.h"
#include <time.h>
#include <immintrin.h>

#include "libamx.h"

#ifdef  _DEBUG_
#define DEBUG_INFO(format, ...)		printf("[DEBUG]: " format, ##__VA_ARGS__)
#else
#define DEBUG_INFO(format, ...)
#endif

#define PROF_TMR_DECL()     struct timespec start, end;double time_used, perf;long long tsc_start, tsc_end
#define PROF_TMR_START()    clock_gettime(CLOCK_MONOTONIC_RAW, &start);tsc_start = rdtsc()
#define PROF_TMR_END()      tsc_end = rdtsc();clock_gettime(CLOCK_MONOTONIC_RAW, &end);time_used = get_time(&start, &end);perf = loop_cnt * ops_per_loop / time_used * 1e-9
#define PROF_GOPS_VALUE     (tsc_end-tsc_start)

#define BIT_TEST(bit_map, pos) (((bit_map) & (0x1 << (pos))) ? 1 : 0)

#define AMX_ALIGN(x)        __attribute__((aligned(x)))
#define AMX_ALIGN_STRUCT(x) struct __attribute__((aligned(x)))
#define AMX_ALIGN_CLASS(x)  class  __attribute__((aligned(x)))

#define DisplayIntegerMatrix(matrix, size, title, flag) {\
    if (title) \
    { \
        printf("\n\033[0;31m%s\033[0m", title); \
    } \
    else \
    { \
        printf("\033[0;31m%s\033[0m", #matrix": "); \
    } \
    for (int i = 0; i < size; i++) \
    { \
        printf("%10d", (matrix)[i]); \
        if (flag && ((i + 1) % flag == 0)) \
        { \
            putchar(10); \
        } \
    } \
    putchar(10); \
}

struct cpuid_t
{
    unsigned int ieax;
    unsigned int iecx;
    unsigned int eax;
    unsigned int ebx;
    unsigned int ecx;
    unsigned int edx;
};

void amx_dct_16x16(int16_t *coefficients);
void do_cpuid_read(uint32_t eax, uint32_t ecx);
void do_cpuid_featuredetect(void);
void dump_tilecfg_reg(struct TileConfig *tcfg, const char* name);
uint64_t xgetbv(uint32_t index);
void req_xtiledata_permission(void);

#endif
